package com.iteaj.iot.plc.omron;

import com.iteaj.iot.plc.PlcException;
import com.iteaj.iot.plc.PlcProtocolType;
import com.iteaj.iot.utils.ByteUtil;
import com.iteaj.iot.plc.I18n;

public final class OmronUtils {

    /**
     * 分析响应数据 并且获取读取的数据
     * @param response
     * @param isRead
     * @return
     */
    public static byte[] responseValidAnalysis(byte[] response, boolean isRead) {
        validErrorCode(response);

        byte[] result = new byte[response.length - 16];
        System.arraycopy(response, 16, result, 0, result.length);
        return udpResponseValidAnalysis(result, isRead);
    }

    public static int getErrorCode(byte[] response) {
        if (response.length >= 16) {

            // 提取错误码校验
            byte[] buffer = new byte[4];
            buffer[0] = response[15];
            buffer[1] = response[14];
            buffer[2] = response[13];
            buffer[3] = response[12];

            return ByteUtil.bytesToInt(buffer, 0);
        }

        throw new PlcException("数据接收异常", PlcProtocolType.Omron);
    }

    /**
     * 返回状态
     * @param response
     * @return
     */
    public static boolean isSuccess(byte[] response) {
        return getErrorCode(response) == 0;
    }

    /**
     * 校验plc错误码 0.成功 其余的都是错误
     * @param response
     * @throws PlcException 失败直接抛出异常
     */
    public static void validErrorCode(byte[] response) throws PlcException {
        int errorCode = getErrorCode(response);
        if(errorCode > 0) {
            throw new PlcException(getStatusDescription(errorCode), PlcProtocolType.Omron);
        }
    }

    /**
     * 验证欧姆龙的Fins-Udp返回的数据是否正确的数据，如果正确的话，并返回所有的数据内容<br />
     * @param response 来自欧姆龙返回的数据内容
     * @param isRead 是否读取
     * @return 带有是否成功的结果对象
     */
    public static byte[] udpResponseValidAnalysis(byte[] response, boolean isRead) {
        if (response.length >= 14) {
            int err = (response[12] & 0xff) * 256 + (response[13] & 0xff);

            if (!isRead) {
                return new byte[0];
            } else {
                byte[] content = new byte[response.length - 14];
                if (content.length > 0) {
                    System.arraycopy(response, 14, content, 0, content.length);
                } else {
                    throw new PlcException(getStatusDescription(err), PlcProtocolType.Omron);
                }

                if(response[10] == 0x00 & response[11] == 0x00) {
                    return content;
                } else if(response[10] == 0x01 & response[11] == 0x04){ // 多个数据块读取的情况，还需要二次解析数据
                    byte[] buffer = content.length > 0 ? new byte[content.length * 2 / 3] : new byte[0];
                    for (int i = 0; i < content.length / 3; i++) {
                        buffer[i * 2 + 0] = content[i * 3 + 1];
                        buffer[i * 2 + 1] = content[i * 3 + 2];
                    }

                    return buffer;
                } else {
                    System.out.println("----------------- [欧姆龙]未知状态["+response[10]+"]["+response[11]+"] --------------");
                    return content;
                }
            }
        } else {
            throw new PlcException("数据接收异常", PlcProtocolType.Omron);
        }
    }
    private static byte getModel(OmronFinsModel model, boolean isBit) {
        return isBit ? model.getBit() : model.getWord();
    }

    /**
     * 获取错误信息的字符串描述文本
     * @param err 错误码
     * @return 文本描述
     */
    public static String getStatusDescription(int err) {
        switch (err) {
            case 0:
                return I18n.errorConst.OmronStatus0();
            case 1:
                return I18n.errorConst.OmronStatus1();
            case 2:
                return I18n.errorConst.OmronStatus2();
            case 3:
                return I18n.errorConst.OmronStatus3();
            case 20:
                return I18n.errorConst.OmronStatus20();
            case 21:
                return I18n.errorConst.OmronStatus21();
            case 22:
                return I18n.errorConst.OmronStatus22();
            case 23:
                return I18n.errorConst.OmronStatus23();
            case 24:
                return I18n.errorConst.OmronStatus24();
            case 25:
                return I18n.errorConst.OmronStatus25();
            default:
                return I18n.errorConst.UnknownError();
        }
    }
}
